package com.yzg;

import lombok.extern.slf4j.Slf4j;

import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author misterWei
 * @create 2020年04月27号:21点35分
 * @mailbox forcontinue@163.com
 * 线程设计模式-  保护式暂停_等待&返回
 */
@Slf4j(topic = "c.RpcService")
public class RpcService {

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            new ResultRequest().start();
        }
        TimeUnit.SECONDS.sleep(1);
        for (Integer id : Coordinator.getIds()) {
            new ResultResponse(id,"内容 = "+id).start();
        }
    }

}

/**
 * 结果等待方
 */
@Slf4j(topic = "c.ResultRequest")
class ResultRequest extends Thread{

    @Override
    public void run() {
        //创建一个结果集
        GuardedObject guardedObject = Coordinator.guardedObject();
        Object content = guardedObject.getContent(5000);
        log.debug("结果接收方 ID为:{} 结果为:{}",guardedObject.getId(),content);
    }
}


/**
 * 结果产生方
 */
@Slf4j(topic = "c.ResultResponse")
class ResultResponse extends Thread{
    private Integer id;
    private Object content;
 public ResultResponse(Integer id ,Object content){
     this.id = id;
     this.content = content;
 }
    @Override
    public void run() {
        GuardedObject guardedObject = Coordinator.guardedObject(id);
        guardedObject.setContent(content);
        log.debug("结果产生方 ID为:{} 结果为:{}",guardedObject.getId(),content);
    }
}

/**
 * 协调者对象,协调结果集,并对外提供其控制方法 符合ocp原则
 */
@Slf4j(topic = "c.Coordinator")
 class Coordinator{
    private static int i;
    //线程安全的 Hashtable
    private static final Map<Integer,GuardedObject> guardedMaps = new Hashtable<>(16);

    //获取唯一ID
    private static synchronized int getId(){
        return i++;
    }

    //创建结果集对象
    public static GuardedObject guardedObject(){
        GuardedObject guardedObject = new GuardedObject(getId());
        guardedMaps.put(guardedObject.getId(),guardedObject);
        return guardedObject;
    }
    //根据Id获取Map中的数据
    public static GuardedObject guardedObject(Integer id){
        //实时减少 map中的数据 防止内存泄漏
        return guardedMaps.remove(id);
    }
    //获取所有id
    public static Set<Integer> getIds(){
        return guardedMaps.keySet();
    }


}


/**
 * 结果集产生 - 等待&唤醒 解耦实体类
 */
class  GuardedObject{
   private static final Object lock = new Object();
    private Integer id;

    public GuardedObject(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    private Object content;
    //参考 Thread 的join方法进行超时逻辑实现
    public Object getContent(long timeout){
        synchronized (lock){
            long base = System.currentTimeMillis();
            long now = 0;
            while (content == null){
                long delay = timeout - now;
                if (delay <= 0) {
                    break;
                }
                try {
                    lock.wait(timeout);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                now = System.currentTimeMillis() - base;
            }
        }
        return content;
    }

    // 结果映射并赋值
    public void setContent(Object content){
        synchronized (lock){
            this.content = content;
            lock.notifyAll();
        }
    }


}
